from django.db import connection, transaction


def dictfetchall(cursor):
    "Returns all rows from a cursor as a dict"
    desc = cursor.description
    return [dict(zip([col[0] for col in desc], row)) \
            for row in cursor.fetchall()]


def find(dict_result, field, value):
    for t in dict_result:
        if t[field] == value:
            return t


class Page:

    @classmethod
    def combine_duplicate_link(cls, links):
        temp = {}
        for url, txt in links:
            if url in temp:
                temp[url] += ',' + txt
            else:
                temp[url] = txt
        return [(url, txt) for url, txt in temp.iteritems()]

    @classmethod
    def update(cls, links):
        if not isinstance(links[0], (tuple, list)):
            links = [links]
        links = cls.combine_duplicate_link(links)
        cursor = connection.cursor()
        cursor.execute('SELECT url, key_word FROM page')
        saved_page = dictfetchall(cursor)
        for url, txt in links:
            t = find(saved_page, 'url', url)
            if not t:
                cursor.execute('INSERT INTO page (url, key_word)'
                               'VALUES (%s, %s)'
                               ,[url, txt])
            elif not txt in t['key_word']:
                cursor.execute('UPDATE page SET key_word = %s'
                               'WHERE url = %s',
                               [t['key_word']+','+txt, url])
        transaction.commit_unless_managed()


class Link:

    @classmethod
    def update(cls, page_url, inner_link_url):
        cursor = connection.cursor()
        cursor.execute('SELECT inner_link_url FROM link '
                       'WHERE page_url = %s', [page_url])
        saved_results = {t[0] for t in cursor.fetchall()}
        for url in inner_link_url:
            if url in saved_results:
                continue
            cursor.execute('INSERT INTO link '
                           '(page_url, inner_link_url)'
                           'VALUES (%s, %s)', [page_url, url])
        transaction.commit_unless_managed()
